/**
 * Created by Administrator on 2017/1/15.
 */

var config = require('./config');

var MJ = require('../MJ/MJ');
var MJRoom = require('../MJ/room').MJRoom;

var Const = require('./const');
var SubCode = require('../subCode');

exports.TTMJRoom = MJRoom.extend({

    init: function(rid, creator, msg) {
        this._super(rid, creator, msg);
        this.setSaveReplay(true);
    },

    checkInit: function() {
        return this._super();
    },

    /******************************************************************
     * 重载的接口
     ******************************************************************/

    initPlayersHandCards: function(startIndex) {
        this._super(startIndex);

        // var self = this;
        // this.enumPlayers(function (eIndex, ePlayer) {
        //     console.log("initPlayersHandCards: " + ePlayer.getIndex() + " => " + self.getDealerIndex());
        //     //ePlayer.initHandCards(this._publicCards.getCards(ePlayer.getInitHandCardNeedNum(), ePlayer.getInitHandCardPreCards()));
        //     if (eIndex == self.getDealerIndex()) {
        //         var preCards = [11,11,11,11,12,12,12,12,13,13,13,13,14,14];
        //         ePlayer.initHandCards(this._publicCards.getCards(ePlayer.getInitHandCardNeedNum(), preCards));
        //     } else {
        //         var preCards = [14,15,15,15,16,16,16,17,17,17,21,21,21];
        //         ePlayer.initHandCards(this._publicCards.getCards(ePlayer.getInitHandCardNeedNum(), preCards));
        //     }
        // }.bind(this), startIndex);
        //
        // this._sendPublicCardChanged();
    },

    getRoomConfig: function() {
        var cfg = this._super();
        cfg.destroyWaitTime = 300;
        cfg.respDestroyIgnoreOffline = false;
        return cfg;
    },

    getReconnectInfo: function(rePlayer) {
        var info = this._super(rePlayer);

        this.enumPlayers(function(eIndex, ePlayer){
            if (this._hangupTask.getPlayerTask(eIndex, MJ.Task.MOPAI)) {
                info.onPlayerMoPai = true;
                return false;
            }
        }.bind(this));

        return info;
    },

    onBeforeStartNewRound: function() {
        this._super();
    },

    onAfterStartNewRound: function() {
        this._super();
        this.initPlayersHandCards();
        this.startPlay();
    },

    startPlay: function() {
        this._startPlay();
    },

    _startPlay: function() {
        this._changeCurPlay(this.getDealerIndex());
        this._doCheckNewCardHangupTask();
    },

    onBeforePlayCard: function(player, msg, card) {
        var code = this._super(player, msg, card);
        if (code) {
            return code;
        }

        if (player.isBaoTing() && card != player.getLastCard()) { //天听不能换牌
            return SubCode.MJ_IS_BAOTING;
        }

        if (!player.getShaiPai().isBaiPai()) {  // 玩家没有摆牌
            this.enumPlayers(function(eIndex, ePlayer){
                if (eIndex != player.getIndex() && !ePlayer.isRoundHu()) {  // 他方晒牌且胡这张牌，我方不能打出
                    var playerSaiPai = ePlayer.getShaiPai();
                    if (playerSaiPai.isBaiPai() && playerSaiPai.containsHuCard(card)) {
                        code = SubCode.MJ_SHAIPAI_HAS_CARD;
                        return false;
                    }
                }
            });

            var self = this;

            // 玩家因为别人摆牌的原因不能出牌
            if (code) {
                // 检查是否所有牌都是炮牌
                var allBaiHuCard = true;
                ExObject.each(player.getHandCards(), function(eCard, eCardNum){
                    eCard = +eCard; eCardNum = +eCardNum;
                    if (eCardNum > 0) {
                        if (!self.isCardIsOtherBaiHu(player.getIndex(), eCard)) {
                            allBaiHuCard = false;
                            return false;
                        }
                    }
                });

                if (allBaiHuCard) {
                    // 玩家所有手牌都是炮牌，也要出牌
                    code = Code.SUCCESS;
                }
            }

            return code;
        }
    },

    onAfterGangTask: function(player, card, gangTask, gangInfo) {
        if(!this._super(player, card, gangTask, gangInfo)) {
            return false;
        }

        if (player.getGangCount() == 4) {   // 4杠自动胡牌(十八学士)
            this._hangupTask.addHuTask(player.getIndex(), 0, player.getIndex(), Const.Pattern.ShiBaXueSi, []);
            this._hangupTask.submitTaskWithoutCheck(player.getIndex(), MJ.Task.HU);
            this._sendHangupTask();
            return false;
        }

        return true;
    },

    checkNewCardHangupTask: function() {
        var player = this.getCurPlayer();

        var huIndexs = [];
        var huPattern = player.checkHu();
        if (huPattern != Const.Pattern.NONE) {
            var rules = [];
            if (this.getCurGang()) {
                rules.push(Const.ScoreRule.GSH);
            }

            if (this.getHideOption("TDH")) {
                if (player.isFirstHand()) {
                    rules.push((player.getIndex() == this.getDealerIndex()) ? Const.ScoreRule.TH : Const.ScoreRule.DIHU);
                }
            }

            var card = player.getLastCard() || player.getInitLastCard();
            this._hangupTask.addHuTask(player.getIndex(), card, player.getIndex(), huPattern, rules);
            huIndexs.push(player.getIndex());
        }

        var gangArray = player.checkGang();
        if (gangArray.length > 0) {
            var gangTask = null;
            if (!player.isBaoTing()) {
                gangTask = gangArray[0];
            } else {
                for (var i = 0; i < gangArray.length; ++i) {
                    if (!player.checkTingChangeIfGang(gangArray[i])) {
                        gangTask = gangArray[i]; break;
                    }
                }
            }
            if (gangTask) {
                this._hangupTask.addGangTask(player.getIndex(), gangTask);
            }
        }

        // if (this.getPublicCards().getRemainNum() <= 4) {
        //     huIndexs.forEach(function(eIndex) {
        //         this._hangupTask.submitTaskWithoutCheck(eIndex, MJ.Task.HU);
        //     }.bind(this));
        // }
    },

    checkPlayCardHangupTask: function(card) {
        var dealerIndex = this.getDealerIndex();
        var curPlay = this.getCurPlay();
        var curPlayer = this.getCurPlayer();    // 当前打牌玩家
        var huIndexs = [];

        this.enumPlayers(function(eIndex, ePlayer) {
            if (eIndex != curPlay && !ePlayer.isRoundHu()) {
				ePlayer.resetLastGangG(); // 重置连杠信息
				
                if (!ePlayer.isPassHu() && ePlayer.getBaoTingPassHuTimes() < 1) {
                    var huPattern = ePlayer.checkHuWithCard(card);
                    if (huPattern != Const.Pattern.NONE) {
                        var rules = [];

                        if (this.getCurGang() > 0) {
                            rules.push(Const.ScoreRule.GSP);
                        }

                        if (this.getHideOption("TDH")) {
                            if ((curPlayer.getPlayHand() == 1) && curPlayer.isDealer()) {  // 庄家打第一手牌
                                rules.push(Const.ScoreRule.DIHU);
                            }
                        }

                        this._hangupTask.addHuTask(ePlayer.getIndex(), card, curPlay, huPattern, rules);
                        huIndexs.push(eIndex);
                    }
                }

                if (ePlayer.checkPengWithCard(card)) {
                    this._hangupTask.addPengTask(eIndex, card, curPlay);
                }

                if (ePlayer.checkGangWithCard(card)) {
                    var gangTask = {card: card, from: curPlay, gang: MJ.Gang.DIAN};
                    if (!ePlayer.isBaoTing() || !ePlayer.checkTingChangeIfGang(gangTask)) {
                        this._hangupTask.addGangTask(eIndex, gangTask);
                    }
                }
            }
        }.bind(this));

        // if (this.getPublicCards().getRemainNum() <= 4) {
        //     huIndexs.forEach(function(eIndex) {
        //         this._hangupTask.submitTaskWithoutCheck(eIndex, MJ.Task.HU);
        //     }.bind(this));
        // }
    },

    checkGangHangupTask: function(playerIndex, gangInfo) {
        var card = gangInfo.card;
        var huIndexs = [];
        this.enumPlayers(function(eIndex, ePlayer) {
            if (eIndex != playerIndex && !ePlayer.isRoundHu() && !ePlayer.isPassHu() && ePlayer.getBaoTingPassHuTimes() < 1) {
                var huPattern = ePlayer.checkHuWithCard(card);
                if (huPattern != Const.Pattern.NONE) { // 抢杠
                    var rules = [];
                    rules.push(Const.ScoreRule.QG);

                    this._hangupTask.addHuTask(eIndex, card, playerIndex, huPattern, rules);
                    huIndexs.push(eIndex);
                }
            }
        }.bind(this));

        // if (this.getPublicCards().getRemainNum() <= 4) {
        //     huIndexs.forEach(function(eIndex) {
        //         this._hangupTask.submitTask(eIndex, MJ.Task.HU);
        //     }.bind(this));
        // }
    },

    checkGangTaskQG: function(task, gangInfo) {
        return gangInfo.gang == MJ.Gang.BA;
    },

    checkHuSettlement: function() {
        return this.getHuPlayerCount() >= (this.getPlayingPlayerCount() - 1);
    },

    onSettlementHuTask: function(task) {
        var playerIndex = task.playerIndex;
        var pattern = task.pattern;
        var card = task.card;
        var from = task.from;
        var rules = task.rules;
        var huPlayer = this.getPlayerByIndex(playerIndex);

        var isZM = (playerIndex == from); // 是否是自摸

        var targetsIndex = [];
        var targets = [];
        var shaiStats = {};
        var fromPlayer = null;

        if (isZM) {
            this.enumPlayers(function(eIndex, ePlayer) {
                if (eIndex != playerIndex && !ePlayer.isRoundHu()) {
                    targetsIndex.push(eIndex);
                    targets.push(ePlayer);

                    if (ePlayer.getShaiPai().isBaiPai()) {
                        shaiStats[eIndex] = 1;

                        // 他放晒牌加番
                        var shaiPaiTarget = Const.ScoreRule.TARGET_SHAIPAI + eIndex;
                        huPlayer.setRoundScoreRule(shaiPaiTarget);
                        huPlayer.addRoundItemScores(shaiPaiTarget, Const.ItemScore[shaiPaiTarget]);
                    }
                }
            });
        } else {
            fromPlayer = this.getPlayerByIndex(from);
            targetsIndex.push(from);
            targets.push(fromPlayer);

            if (this.getPlayerByIndex(from).getShaiPai().isBaiPai()) {
                shaiStats[from] = 1;

                // 他放晒牌加番
                var shaiPaiTarget = Const.ScoreRule.TARGET_SHAIPAI + from;
                huPlayer.setRoundScoreRule(shaiPaiTarget);
                huPlayer.addRoundItemScores(shaiPaiTarget, Const.ItemScore[shaiPaiTarget]);
            }
        }

        if (huPlayer.getShaiPai().isBaiPai()) { // 晒牌加番
            huPlayer.setRoundScoreRule(Const.ScoreRule.SHAIPAI);
            huPlayer.addRoundItemScores(Const.ScoreRule.SHAIPAI, Const.ItemScore[Const.ScoreRule.SHAIPAI]);
        }

        var patternScore = Const.PatternScore[pattern];

        for (var i = 0; i < rules.length; ++i) {
            var rule = rules[i];
            switch (rule) {
                case Const.ScoreRule.QG:
                    if (!isZM) {
                        var targetPlayer = targets[0];
                        if (targetPlayer.getIndex() == this.getCurPlay() && this.getCurGang() > 0) { // 抢杠的被抢玩家一定是当前玩家
                            huPlayer.setRoundScoreRule(rule);
                            huPlayer.addRoundItemScores(rule, Const.ItemScore[rule]);

                            targetPlayer.setRoundScoreRule(rule);
                            targetPlayer.cancelLastGangForQG(card);
                        }
                    }
                    break;
                case Const.ScoreRule.GSP:
                    if (!isZM) {
                        // 杠上炮连杠加番
                        huPlayer.setRoundScoreRule(rule);
                        var ruleScore = (Const.ItemScore[rule] || 1) * fromPlayer.getLastGangGDeep();
                        huPlayer.addRoundItemScores(rule, ruleScore);
                        // if (!task.YPDX) {
                        //     targets[0].transLastGangTo(huPlayer.getIndex());
                        // }
                    }
                    break;
                case Const.ScoreRule.GSH:
                    // 杠上花加番
                    huPlayer.setRoundScoreRule(rule);
                    var ruleScore = (Const.ItemScore[rule] || 1) * huPlayer.getLastGangGDeep();
                    huPlayer.addRoundItemScores(rule, ruleScore);
                    break;
                case Const.ScoreRule.TH:
                    huPlayer.setRoundScoreRule(rule);
                    huPlayer.addRoundItemScores(rule, Const.ItemScore[rule]);
                    break;
                case Const.ScoreRule.DIHU:
                    huPlayer.setRoundScoreRule(rule);
                    huPlayer.addRoundItemScores(rule, Const.ItemScore[rule]);
                    break;
                default:
                    break;
            }
        }

        huPlayer.setRoundResult(isZM ? MJ.Result.ZM : MJ.Result.DH, targetsIndex, card);
        huPlayer.setShaiState(shaiStats);
        huPlayer.setRoundPattern(pattern, patternScore);
        huPlayer.settlementRules();

        this.broadcastReplay("onPlayerHu", {
            playerIndex: playerIndex,
            card: card,
            from: from,
        });
    },

    checkGangNewCard: function() {
        if(this.getOption("SP")) {  // 随时晒牌
            // 杠牌后不摸牌，等待客户端选择摸牌还是晒牌
            return false;
        }
        return this._super();
    },

    checkCurPlayHangupTask: function() {
        // 杠牌后摸牌消息
        var player = this.getCurPlayer();
        var playerIndex = this.getCurPlay();
        if (this.getCurGang() > 0) {
            this._hangupTask.addTask(playerIndex, MJ.Task.MOPAI, {});
            this.broadcastReplay("onPlayerMoPai", {
                playerIndex:    playerIndex
            });
        }
    },

    dealNewCard: function() {
        if (this.isCurRoundFinished()) {
            return;
        }
        if (this.isCurRoundFinished()) {
            return;
        }

        if (!this.getOption("SP")) {    // 不是随时晒牌
            this._super();
            return;
        }

        var player = this.getCurPlayer();
        var tings = player.checkTing();
        if (tings.length == 0) {
            this._super();
        } else {
            if (this.getPublicCards().getRemainNum() > 0) {  // 有牌才摸牌
                this._hangupTask.addTask(player.getIndex(), MJ.Task.MOPAI, {});
                this.broadcastReplay("onPlayerMoPai", {
                    playerIndex:    player.getIndex()
                });
                this._sendHangupTask();
            } else {    // 没牌了就结算
                this.settlementCurRound(this.getRoomConfig().MJsettlementWait);
            }
        }
    },

    onHangupTask: function(task, arg1, arg2) {
        this._super(task, arg1, arg2);

        switch (task) {
            case MJ.Task.MOPAI:
                this.dealHangupTaskMoPai(arg1);
                break;
        }
    },

    handleMoPaiTask: function (player, msg, callback) {
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING});
            return;
        }

        if (!this._hangupTask.exist(player.getIndex())) {
            callback({code: SubCode.TASK_UNMATCHED});
            return;
        }
        callback({});
        player.setWaitHandleTime(0);

        this._hangupTask.submitMoPai(player.getIndex());
    },

    dealHangupTaskMoPai: function (task) {
        logger.debug("room=%d dealHangupTaskMoPai args=%j", this.rid(), task);

        var playerIndex = task.playerIndex;
        var player = this.getPlayerByIndex(playerIndex);

        // 发牌
        this._dealNewCard();
    },


    onSettlement: function() {
        this.enumPlayers(function(eIndex, ePlayer) {
            this._settlementPlayerTing(ePlayer);
        }.bind(this));

        this.enumPlayers(function(eIndex, ePlayer) {
            ePlayer.settlementGangScore();
            ePlayer.settlementPatternScore();
        }.bind(this));

        // 至少有两家未胡牌时查听（叫）
        if (this.getPlayerCount() - this.getHuPlayerCount() >= 2) {
            this.enumPlayers(function(eIndex, ePlayer) {
                if (!ePlayer.isRoundHu() && ePlayer.isRoundTing()) {    // 玩家没有胡牌但是听牌了
                    ePlayer.setRoundScoreRule(Const.ScoreRule.SHAIPAI);
                    ePlayer.addRoundItemScores(Const.ScoreRule.SHAIPAI, Const.ItemScore[Const.ScoreRule.SHAIPAI]);
                }
            }.bind(this));

            this.enumPlayers(function(eIndex, ePlayer) {
                ePlayer.settlementTingScore();
            }.bind(this));
        }
    },

    getSettlementInfo: function() {
        var info = this._super();
        return info;
    },

    onCurRoundFinished: function() {
        this._super();

        // 计算新的庄家(当前轮第一个胡牌的玩家)
        var newDealerIndex = this.getFirstHuPlayerIndex();

        if ((newDealerIndex != 0) && (newDealerIndex != this._dealerIndex)) {
            this._dealerIndex = newDealerIndex;
            this._dealerLZ = 1;
        } else {
            this._dealerLZ++;
        }

        this.broadcastReplay("onDealerChanged", {
            dealer: this._dealerIndex,
            dealerLZ: this._dealerLZ
        });
    },

    onAfterNewCard: function() {
        var player = this.getCurPlayer();
        player.resetGuoShuiFan();
    },

    /******************************************************************
     * 消息处理
     ******************************************************************/

    handleShaiPai: function(player, msg, callback) {
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING});
            return;
        }

        var playerShaiPai = player.getShaiPai();
        if (playerShaiPai.isBaiPai()) {
            callback({code: Code.ROOM_PLAYER_ALREADY_SAIPAI});
            return;
        }

        var huCards = msg.huCards;
        var baiCards = msg.baiCards;
        var useableGang = msg.useableGang || [];
        playerShaiPai.setBaiPai(true);
        playerShaiPai.setHuCards(huCards);
        playerShaiPai.setBaiCards(baiCards);
        playerShaiPai.setUsableGang(useableGang);

        huCards.forEach(function(huCard){   // 移除巴杠任务
            this._hangupTask.removeGangTask(MJ.Gang.BA, huCard);
        }.bind(this));
        this._hangupTask.check();

        this.broadcastReplay("onPlayerShaiPai", {
            playerIndex: player.getIndex(),
            huCards: huCards,
            baiCards: baiCards
        });

        callback({});
    },

    handleShaiPaiChanged: function(player, msg, callback) {
        var huCards = msg.huCards || [];
        var baiCards = msg.baiCards || [];
        var playerShaiPai = player.getShaiPai();
        if (playerShaiPai.isBaiPai()) {
            playerShaiPai.setHuCards(huCards);
            playerShaiPai.setBaiCards(baiCards);

            this.broadcastReplay("onShaiPaiChanged", {
                playerIndex: player.getIndex(),
                huCards: huCards,
                baiCards: baiCards
            });
        }
        callback({});
    },

    /******************************************************************
     * 功能接口
     ******************************************************************/

    /**
     * 结算玩家是否听牌
     * @param player
     * @private
     */
    _settlementPlayerTing: function(player) {
        //已听牌玩家不用再检测
        if (player.isRoundTing()) {
            return;
        }

        // 对未胡牌的玩家检查是否听牌
        var tings = player.checkTing();
        var pattern = Const.Pattern.NONE;
        var patternScore = -1;
        var patternRules = null;

        for (var i = 0; i < tings.length; ++i) {
            var ting = tings[i];

            var rules = player.settlementTingRules(ting.pattern, ting.card);
            var score = Const.PatternScore[ting.pattern] + ExObject.sumValue(rules);
            if (score > patternScore) {
                pattern = ting.pattern;
                patternScore = score;
                patternRules = rules;
            }
        }

        player.setRoundPattern(pattern, 0);
        player.setTingRules(patternRules);
    },

    //-------------------------------------------------------------------------

    /**
     * 判断牌是不是别人摆牌要胡的牌
     * @param playerIndex           玩家索引
     * @param card                  牌
     * @param includeHuPlayer       是否检查已经胡牌的玩家
     */
    isCardIsOtherBaiHu: function(playerIndex, card, includeHuPlayer) {
        var self = this;
        var isBaiHu = false;
        self.enumPlayers(function(eIndex, ePlayer){
            if (eIndex != playerIndex) {
                if (ePlayer.isRoundHu() && !includeHuPlayer) {
                    return;
                }

                var playerSaiPai = ePlayer.getShaiPai();
                if (playerSaiPai.isBaiPai() && playerSaiPai.containsHuCard(card)) {
                    isBaiHu = true;
                    return false;
                }
            }
        });
        return isBaiHu;
    }
});